#ifndef ParserBase_h_included
#define ParserBase_h_included

#include <vector>
#include <iostream>

// $insert debugincludes
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <iomanip>

namespace // anonymous
{
    struct PI_;
}


class ParserBase
{
    public:
// $insert tokens

    // Symbolic tokens:
    enum Tokens_
    {
        ID = 257,
        UNARY,
    };

// $insert STYPE
using STYPE_ = int;

    private:
        int d_stackIdx_;
        std::vector<size_t>   d_stateStack_;
        std::vector<STYPE_>  d_valueStack_;

    protected:
        enum Return_
        {
            PARSE_ACCEPT_ = 0,   // values used as parse()'s return values
            PARSE_ABORT_  = 1
        };
        enum ErrorRecovery_
        {
            DEFAULT_RECOVERY_MODE_,
            UNEXPECTED_TOKEN_,
        };
        bool        d_debug_;
        size_t      d_nErrors_;
        size_t      d_requiredTokens_;
        size_t      d_acceptedTokens_;
        int         d_token_;
        int         d_nextToken_;
        size_t      d_state_;
        STYPE_    *d_vsp_;
        STYPE_     d_val_;
        STYPE_     d_nextVal_;

        ParserBase();

// $insert debugdecl
        static std::ostringstream s_out_;

        std::string symbol_(int value) const;
        std::string stype_(char const *pre, STYPE_ const &semVal,
                            char const *post = "") const;
        static std::ostream &dflush_(std::ostream &out);
        void ABORT() const;
        void ACCEPT() const;
        void ERROR() const;
        void clearin();
        bool debug() const;
        void pop_(size_t count = 1);
        void push_(size_t nextState);
        void popToken_();
        void pushToken_(int token);
        void reduce_(PI_ const &productionInfo);
        void errorVerbose_();
        size_t top_() const;

    public:
        void setDebug(bool mode);
}; 

inline bool ParserBase::debug() const
{
    return d_debug_;
}

inline void ParserBase::setDebug(bool mode)
{
    d_debug_ = mode;
}

inline void ParserBase::ABORT() const
{
    // $insert debug
    if (d_debug_)
        s_out_ <<  "ABORT(): Parsing unsuccessful" << "\n" << dflush_;
    throw PARSE_ABORT_;
}

inline void ParserBase::ACCEPT() const
{
    // $insert debug
    if (d_debug_)
        s_out_ <<  "ACCEPT(): Parsing successful" << "\n" << dflush_;
    throw PARSE_ACCEPT_;
}

inline void ParserBase::ERROR() const
{
    // $insert debug
    if (d_debug_)
        s_out_ <<  "ERROR(): Forced error condition" << "\n" << dflush_;
    throw UNEXPECTED_TOKEN_;
}


// As a convenience, when including ParserBase.h its symbols are available as
// symbols in the class Parser, too.
#define Parser ParserBase


#endif


